package view.gui;

import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;


import model.vos.ErrorUserException;
import model.vos.Usuarios;
import model.SecurityUsers;

/**
 * Componete que valida si un usuario es valido o no
 * 
 * @author Manuel
 */
public class UserAuthenticationDialog extends JDialog implements ActionListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -2740412075910574032L;
	
	final Color ERROR_MESSAGE_COLOR = Color.RED;
	final Color ERROR_COLOR = Color.PINK;
	final Color DEFAULT_COLOR = Color.WHITE;

	// Combobox editable con la lista de los usuarios
	private JComboBox cbxUserList;
	// Caja de texto para introducir el password
	private JPasswordField txtPassword;
	// Etiqueta para el mesaje de error
	private JLabel lblErrorMessage;
	// Boton que dispara el evento de validacion
	private JButton btnDoValidation = null;
	// Boton que cancela y cierra el dialogo de validacion
	private JButton btnCancel = null;
	// Arreglo temporal con la lista de los usuarios que se han logueado
	static private ArrayList<String> userList;
	// Propiedad para determinar si el usuario se logueo correctamente
	private boolean isValidUser = false;
	// color del mensage de error
	private static Color defaultColorBg = null;
	// Usuario que sera validado
	private Usuarios usuarios;
	// Usuario logueado en la refaccionaria
	private Usuarios currentUser;

	/**
	 * Constructor de la clase que recibe dos parametros
	 * 
	 * @param frame es el contenedor que hace la llamada del dialogo.
	 * @param modal forma en que se abre el dialogo, la cual deshabilita el contenedor que hace la apartura
	 */
	public UserAuthenticationDialog(LoginManager frame, boolean modal) {
		super(frame, modal);
		defaultColorBg = this.getBackground();

		// Usuario actualmente logueado
		currentUser = frame.getUser();

		initComponets();
		layoutDesign();
		this.setPreferredSize(new Dimension(280, 160));
		this.setResizable(false);
		this.setTitle("AUTOKITS Login");
		this.pack();
		this.setLocationRelativeTo(frame);
		this.setVisible(true);
	}

	/**
	 * Construye el estilo para el Layout del componente
	 */
	private void layoutDesign() {
		this.getContentPane().setLayout(
				new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
		JPanel panel = new JPanel();
		panel.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
		panel.setLayout(new GridBagLayout());
		GridBagConstraints constrain = new GridBagConstraints();
		constrain.fill = GridBagConstraints.EAST;
		constrain.gridx = 1;
		constrain.gridy = 0;
		constrain.weighty = 1;
		JLabel lblUser = new JLabel("Usuario:");
		lblUser.setAlignmentX(RIGHT_ALIGNMENT);
		panel.add(lblUser, constrain);
		constrain.fill = GridBagConstraints.HORIZONTAL;
		constrain.gridx = 0;
		constrain.gridy = 0;
		panel.add(cbxUserList, constrain);
		constrain.weighty = 1;
		JLabel lblPassword = new JLabel("Password:");
		constrain.fill = GridBagConstraints.HORIZONTAL;
		constrain.gridx = 1;
		constrain.gridy = 1;
		panel.add(lblPassword, constrain);
		constrain.fill = GridBagConstraints.HORIZONTAL;
		constrain.gridx = 0;
		constrain.gridy = 1;
		panel.add(txtPassword, constrain);
		this.add(panel);
		lblErrorMessage.setAlignmentX(CENTER_ALIGNMENT);
		this.add(lblErrorMessage);

		panel = new JPanel();
		panel.setAlignmentX(CENTER_ALIGNMENT);
		panel.add(btnDoValidation);
		panel.add(btnCancel);
		this.add(panel);
	}

	/**
	 * Metodo que regrasa la referencia del objeto con la informacion del usuario que se autentico en el proceso de validacion
	 * 
	 * @return referencia a un objeto de tipo User
	 */
	public Usuarios getAuthenticatedUser() {
		return this.usuarios;
	}

	/**
	 * Metodo que regresa true en caso que el usuario se autentico de forma correcta y regresa false en caso contrario
	 * 
	 * @return el estado de la validacion true o false
	 */
	public boolean isValidUser() {
		return isValidUser;
	}

	/**
	 * Metodo que inicializa los componentes
	 */
	private void initComponets() {
		// Validamos que la lista strUserList este inicializada
		if (userList == null) {
			userList = new ArrayList<String>();
		}
		cbxUserList = new JComboBox(userList.toArray());
		cbxUserList.setPreferredSize(new Dimension(180, 30));
		cbxUserList.setEditable(true);
		cbxUserList.setFont(new Font("Verdana", Font.BOLD, 15));
		txtPassword = new JPasswordField();
		txtPassword.setPreferredSize(new Dimension(180, 30));
		txtPassword.setFont(new Font("Verdana", Font.BOLD, 15));
		lblErrorMessage = new JLabel(".");
		// Este es un hack, para poner la etiqueta de mensaje sin que al
		// mostrala tenga,
		// un efecto como de salto en los componentes superiores a la etiqueta
		lblErrorMessage.setForeground(defaultColorBg);

		btnDoValidation = new JButton("Aceptar");
		btnDoValidation.addActionListener(this);

		btnCancel = new JButton("Cancelar");
		btnCancel.addActionListener(this);

	}

	/**
	 *Metodo que implementa la interfaz de ActionListener, aqui se evaluan las
	 * acciones despues de dar click en el boton de Aceptar, o el boton de Cancelar
	 */
	@SuppressWarnings("deprecation")
	public void actionPerformed(ActionEvent e) {
		// En caso que el boton que se le dio click sea el de Aceptar se realiza la validacion
		if (btnDoValidation == e.getSource()) {
			String userName = "";
			if (cbxUserList.getSelectedItem() != null) {
				userName = cbxUserList.getSelectedItem().toString().trim();
			}
			String password = txtPassword.getText().trim();
			doUserValidation(userName, password);
		}
		// En caso que el boton que se di click es el de cancelar
		else if (btnCancel == e.getSource()) {
			isValidUser = false;
			setVisible(false);
		}
	}

	/**
	 * Metodo que efectua la validacion del usuario
	 * Se valida que los campos nombre de usuario y password, sean requeridos
	 * 
	 * @param userName Nombre de usuario
	 * @param password Passsword
	 */
	private void doUserValidation(String userName, String password) {
		int privilegios;
		// Validamos que los campos no esten vacios, esto es para hacerlos requeridos
		if (userName.length() == 0) {
			cbxUserList.setBackground(ERROR_COLOR);
			cbxUserList.requestFocus();
			cbxUserList.setToolTipText("Introduzca el nombre de usuario");
			lblErrorMessage.setText("Introduzca el nombre de usuario");
			lblErrorMessage.setForeground(ERROR_MESSAGE_COLOR);
			return;
		}
		if (password.length() == 0) {
			txtPassword.setBackground(ERROR_COLOR);
			txtPassword.requestFocus();
			txtPassword.setToolTipText("Introduzca el password");
			lblErrorMessage.setText("Introduzca el password");
			lblErrorMessage.setForeground(ERROR_MESSAGE_COLOR);
			return;
		}
		cbxUserList.setBackground(DEFAULT_COLOR);
		txtPassword.setBackground(DEFAULT_COLOR);
		// Se agrega el nombre del usuario a la lista desplegable-editable
		this.addUserToList(userName);
		try {
			// Hacemos la llamada del servicio de validacion
			isValidUser = SecurityUsers.isValidUser(userName, password);
			if (isValidUser) {
				String type = SecurityUsers.type(userName);
				usuarios = new Usuarios(userName, password, type);
				String username = usuarios.getName();  
				
				String privilegio=usuarios.getType();
				if(privilegio.equals("admin")){
					LoginManager.setUsername(username);
					LoginManager.setPrivilegios(1);
					new Principal();
				}
				else{					
					LoginManager.setPrivilegios(2);
					LoginManager.setUsername(username);
					new Principal();
				}
				//if (!currentUser.getName().equals(Constants.USER_ANONYMUS)) {
				if (currentUser.getName() != null) {//valida que el usuario no este vacio
					if (!currentUser.equals(usuarios)) {
						cbxUserList.requestFocus();
						lblErrorMessage
								.setText("El usuario no coincide con el que esta en sesion");
						lblErrorMessage.setForeground(Color.BLUE);
						isValidUser = false;
					}
				}

			}

		} catch (ErrorUserException exception) {
			cbxUserList.requestFocus();
			cbxUserList.setBackground(ERROR_COLOR);
			txtPassword.setBackground(ERROR_COLOR);
			cbxUserList.setToolTipText("Usuario no valido");
			txtPassword.setToolTipText("Usuario no valido");
			lblErrorMessage.setText("Usuario no valido");
			lblErrorMessage.setForeground(ERROR_MESSAGE_COLOR);
		}
		setVisible(!isValidUser);
	}

	/**
	 * Agrega un usuario a la lista temporal de usuarios que se han logueado al sistema
	 * el metodo valida si el usuario ya ha sido agregado a la lista para no agregarlo nuevamente
	 * 
	 * @param userName nombre de usuario que se agrega
	 */
	private void addUserToList(String userName) {
		boolean isRepeatedUser = false;
		if (userList == null) {
			userList = new ArrayList<String>();
		}
		// Validacion para no agregar un nombre de usuario repetido
		for (String usrName : userList) {
			if (usrName.compareTo(userName) == 0) {
				isRepeatedUser = true;
				break;
			}
		}
		// Si no es un nombre de usuario repetido lo agregamos a la lista
		if (!isRepeatedUser) {
			userList.add(userName);
			cbxUserList.addItem(userName);
		}
	}

}
